/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       dialog_score.cpp

	$Header: /game/dialog_score.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include <algorithm>

#include "dialog_score.h"

#include "adventure_frame.h"
#include "adventure_map.h"
#include "army.h"
#include "bitmap_group_cache.h"
#include "bitmap_layer_cache_window.h"
#include "bound_handler.h"
#include "button.h"
#include "button_cache.h"
#include "combat_model_window.h"
#include "combat_result.h"
#include "creature_icon_window.h"
#include "creature_select_window.h"
#include "creature_traits.h"
#include "creature_array.h"
#include "debug_message.h"
#include "dialog_high_score.h"
#include "enum_operations.h"
#include "external_string.h"
#include "format_string.h"
#include "high_scores.h"
#include "interface_help.h"
#include "item_help_block.h"
#include "minimum_maximum.h"
#include "music.h"
#include "player.h"
#include "replace_keywords.h"
#include "report_combat_results.h"
#include "simple_dialog.h"
#include "score_computer.h"
#include "sound.h"
#include "sound_cache.h"
#include "standard_fonts.h"
#include "text_window.h"
#include "text_edit_window.h"
#include "town.h"


static t_bitmap_group_cache g_layout( "dialog.win" );
static t_bitmap_group_cache g_difficulty_icons( "icons.difficulty_60" );
extern t_button_cache g_ok_button;

namespace
{
	t_external_string const k_easy( "easy.score" );
	t_external_string const k_normal( "normal.score" );
	t_external_string const k_hard( "hard.score" );
	t_external_string const k_expert( "expert.score" );
	t_external_string const k_impossible( "impossible.score" );
	t_external_string const k_town_title( "town_title.score" );
	t_external_string const k_hero_title( "hero_title.score" );
	t_external_string const k_exploration_title( "exploration_title.score" );
	t_external_string const k_artifacts_title( "artifacts_title.score" );
	t_external_string const k_quests_title( "quests_title.score" );
	t_external_string const k_wealth_title( "wealth_title.score" );
	t_external_string const k_army_size_title( "army_size_title.score" );
	t_external_string const k_battles_won_title( "battles_won_title.score" );
	t_external_string const k_time_title( "time_title.score" );
	t_external_string const k_map_difficulty_title( "map_difficulty_title.score" );
	t_external_string const k_player_difficulty_title( "player_difficulty_title.score" );
	t_external_string const k_week( "week.score" );
	t_external_string const k_battles_won( "battle_won.score" );
	t_external_string const k_gold_value( "gold_value.score" );
	t_external_string const k_army_value( "army_value.score" );
	t_external_string const k_resource_value( "resource_value.score" );
	t_external_string const k_quests_completed( "quests_completed.score" );
	t_external_string const k_artifacts_collected( "artifacts_collected.score" );
	t_external_string const k_explored( "explored.score" );
	t_external_string const k_towns_owned( "towns_owned.score" );
	t_external_string const k_total( "total.score" );
	t_external_string const k_rank( "rank.score" );
	t_external_string const k_name( "name.score" );
	t_external_string const k_cheater( "cheater.misc" );
} // un-named namespace


// ---------------------------------------------------------------------
// Difficulty to string maps.  (Declared extern in difficulty_level.h)
// ---------------------------------------------------------------------
t_external_string const k_difficulty_text[k_difficulty_count] = 
{
	k_easy, k_normal, k_hard, k_expert, k_impossible 
};
const char * const k_difficulty_icon_names[k_difficulty_count] =
{
	"easy", "normal", "hard", "expert", "impossible"
};
const char * const k_difficulty_help_names[k_difficulty_count] =
{
	"difficulty_easy", "difficulty_normal", "difficulty_hard", "difficulty_expert", "difficulty_impossible"
};


// ---------------------------------------------------------------------
// score dialog
// ---------------------------------------------------------------------
t_score_dialog::t_score_dialog(	t_window* parent,	t_adventure_map const & map, int winner_team )
				: t_bitmap_layer_window( 0, t_screen_point(0,0) ), m_parent( parent ), m_map( map ), m_winner_team( winner_team )
{
	initialize();
}

// ---------------------------------------------------------------------
// add a text item
// ---------------------------------------------------------------------
t_text_window* t_score_dialog::add_text( std::string const& text, std::string const& layer_name, 
							               int size, bool size_explicit, bool center )
{
	t_bitmap_layer const* layer;
	t_screen_rect         rect;
	t_text_window*        text_window;
	t_cached_font         font;

	layer = m_layout->find( layer_name );
	rect = layer->get_rect();
	if( size_explicit )
		font = get_font( size );
	else
		font = get_font( rect.height() / size );
	text_window = new t_text_window( font, rect, this, text, t_pixel_24(0,0,0));
	if( center )
		text_window->set_center_horizontal();
	text_window->set_drop_shadow( true, t_pixel_24(200,200,200));
	return text_window;
}

// -----------------------------------------------------------------------
// score dialog
// -----------------------------------------------------------------------
static t_external_string const k_text_high_score_save_problem( "high_score_save_problem.misc" );
void t_score_dialog::ok_clicked( t_button* button )
{
	bool				new_high_score	= false;
	bool				is_standard		= !m_map.is_multi_scenario();
	t_high_scores_ptr	scores_ptr		= read_high_scores_file();

	// Save the possibly edited player name
	std::string player_name = k_cheater;
	if( !m_map.is_cheater() )
		player_name = m_edit_box->get_text();

	// check high scores
	if ( scores_ptr->check_high_scores( m_map.get_map_name(), m_scores.days, m_scores.final_score, player_name, 
										is_standard, m_scores.creature_index ) )
	{
		new_high_score = true;
	}

	// Close ourselves
	t_window_ptr parent = m_parent;
	close();	// close all child windows too

	// If the high scores just changed, show the dialog
	if( new_high_score )
	{
		// write out the new scores to disk
		if (!write_high_scores_file( scores_ptr ))
		{
			ok_dialog( k_text_high_score_save_problem, true );
		}

		// Present the results
		t_counted_ptr<t_high_score_dialog> dialog;
		dialog = new t_high_score_dialog( parent, *scores_ptr, is_standard );
		dialog->run_modal();
	}
}

// ---------------------------------------------------------------------
// create buttons
// ---------------------------------------------------------------------
void t_score_dialog::create_buttons()
{
	t_screen_rect rect;
	t_button*     button;
	t_help_block const& help = get_help_block( "shared" );


	// create ok button
	rect = m_layout->find( "close_button" )->get_rect();
	button = new t_button( g_ok_button.get(), rect.top_left(), this );
	button->set_click_handler( bound_handler(*this, &t_score_dialog::ok_clicked ) );
	set_help( button, help, "ok" );
}

// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
static void set_creature( t_bitmap_layer_cache_window* window, t_abstract_creature const* stack, int size, bool force_awake_portrait )
{
	t_bitmap_layer_ptr icon;

	icon = stack->get_portrait( size, force_awake_portrait );
	window->set_bitmap( icon );
	window->set_help_balloon_text( stack->get_name() );
}

// ---------------------------------------------------------------------
// create icons
// ---------------------------------------------------------------------
void t_score_dialog::create_icons()
{
	t_bitmap_layer const* layer;
	t_window*             window;
	t_bitmap_layer_cache_window* portrait_window;	
	t_screen_point        point(0,0);
	t_screen_rect         rect;
	t_bitmap_layer_ptr	  icon;

	layer = m_layout->find( "hero_portrait" );
	portrait_window = new t_bitmap_layer_cache_window(	t_bitmap_layer_ptr(), 
														layer->get_rect().top_left(), 
														this, false );
	if( m_scores.strongest_hero )
	{
		icon = m_scores.strongest_hero->get_portrait( 52, true );
		portrait_window->set_bitmap( icon );
		portrait_window->set_help_balloon_text( m_scores.strongest_hero->get_name() );
	}
	
	layer = m_layout->find( "rank_icon" );
	portrait_window = new t_bitmap_layer_cache_window(	t_bitmap_layer_ptr(), 
														layer->get_rect().top_left(), 
														this, false );

	icon = get_creature_portrait( m_scores.creature_index, 52 );
	portrait_window->set_bitmap( icon );

	// hero frame
	layer = m_layout->find( "hero_frame" );
	window = new t_bitmap_layer_window( layer, point, this );

	// rank frame
	layer = m_layout->find( "rank_frame" );
	window = new t_bitmap_layer_window( layer, point, this );

	// player difficulty icon
	layer = m_layout->find( "player_difficulty" );
	rect = layer->get_rect();
	layer = m_difficulty_icons->find( k_difficulty_icon_names[m_map.get_player_difficulty()] ); 
	window = new t_bitmap_layer_window( layer, rect.top_left(), this );
	
	// map difficulty icon
	layer = m_layout->find( "map_difficulty" );
	rect = layer->get_rect();
	layer = m_difficulty_icons->find( k_difficulty_icon_names[m_map.get_map_difficulty()] ); 
	window = new t_bitmap_layer_window( layer, rect.top_left(), this );

	// icons
	layer = m_layout->find( "time" );
	window = new t_bitmap_layer_window( layer, point, this );

	layer = m_layout->find( "battles_won" );
	window = new t_bitmap_layer_window( layer, point, this );

	layer = m_layout->find( "army_size" );
	window = new t_bitmap_layer_window( layer, point, this );

	layer = m_layout->find( "wealth" );
	window = new t_bitmap_layer_window( layer, point, this );

	layer = m_layout->find( "quests" );
	window = new t_bitmap_layer_window( layer, point, this );

	layer = m_layout->find( "artifacts" );
	window = new t_bitmap_layer_window( layer, point, this );

	layer = m_layout->find( "exploration" );
	window = new t_bitmap_layer_window( layer, point, this );

	t_town_type town_type = m_scores.human_player->get_alignment();
	std::string text;

	text = k_town_keyword[town_type];
	text += "_town";

	layer = m_layout->find( text );
	window = new t_bitmap_layer_window( layer, point, this );

}


// ---------------------------------------------------------------------
// create all the text to go in each text box
// ---------------------------------------------------------------------
void t_score_dialog::create_text()
{
	std::string text;
	t_screen_point        point(0,0);
	t_screen_rect         rect;

//			std::string hero_list = format_hero_list( *m_armies[k_side_attacker] );
//			text = replace_keywords( k_player_surrenders, "%hero_list", hero_list, "%town_name", m_dest_town_name );

	add_text( k_town_title, "town_title", 1, false );
	add_text( k_hero_title, "hero_title", 1, false );
	add_text( k_exploration_title, "exploration_title", 1, false );
	add_text( k_artifacts_title, "artifacts_title", 1, false );
	add_text( k_quests_title, "quests_title", 1, false );
	add_text( k_wealth_title, "wealth_title", 1, false );
	add_text( k_army_size_title, "army_size_title", 1, false );
	add_text( k_battles_won_title, "battles_won_title", 1, false );
	add_text( k_time_title, "time_title", 1, false );
	add_text( k_map_difficulty_title, "map_difficulty_title", 1, false );
	add_text( k_player_difficulty_title, "player_difficulty_title", 1, false );

	//
	// calculate and post all the score values
	//

	t_map_size		map_size = m_map.get_map_size_type();
	t_difficulty	map_difficulty = m_map.get_map_difficulty();
	t_difficulty	player_difficulty = m_map.get_player_difficulty();

	// player difficulty points
	text = format_string( "%s\n%i%%", k_difficulty_text[player_difficulty].c_str(), 
						  m_scores.player_difficulty_percentage );
	add_text( text, "player_difficulty_text", 2, false );

	// map difficulty
	text = format_string( "%s\n%i%%", k_difficulty_text[map_difficulty].c_str(), 
						  m_scores.map_difficulty_percentage );
	add_text( text, "map_difficulty_text", 2, false );

	// time points
	text = format_string( "%s %i\n%i", k_week.c_str(), ( m_map.get_day() / k_days_per_week ) + 1,
						  m_scores.time_points );
	add_text( text, "time_text", 2, false );

	// battles won points
	text = format_string( "%s %i\n%i", k_battles_won.c_str(), m_scores.battles_won, 
						  m_scores.battles_won_points );
	add_text( text, "battles_won_text", 2, false );

	// army size points
	text = format_string( "%s %i\n%i", k_army_value.c_str(), m_scores.total_creature_gold_value,
						  m_scores.army_size_points );
	add_text( text, "army_size_text", 2, false );

	// wealth points
	text = format_string( "%s %i\n%i", k_gold_value.c_str(), m_scores.resource_value, 
						  m_scores.wealth_points );
	add_text( text, "wealth_text", 2, false );

	// quests points
	text = format_string( "%s %i\n%i", k_quests_completed.c_str(), m_scores.quests_completed, 
						  m_scores.quest_points );
	add_text( text, "quests_text", 2, false );

	// artifacts points
	text = format_string( "%s %i\n%i", k_artifacts_collected.c_str(), m_scores.artifacts_collected, 
						  m_scores.artifact_points );
	add_text( text, "artifacts_text", 2, false );

	// exploration points
	int explored = (int)(m_scores.percent_explored * 100);
	text = format_string( "%i %s\n%i", explored, k_explored.c_str(), 
						  m_scores.exploration_points );
	add_text( text, "exploration_text", 2, false );

	// best hero points
	text = format_string( "%s\n%i", m_scores.hero_name.c_str(), m_scores.main_hero_points );
	add_text( text, "hero_text", 2, false );

	// towns owned
	text = format_string( "%s %i\n%i", k_towns_owned.c_str(), m_scores.town_count, m_scores.town_points );
	add_text( text, "town_text", 2, false );

	// total score
	text = format_string( "%s: %i", k_total.c_str(), m_scores.final_score );
	add_text( text, "score", 1, false, false );

	// rank
	m_scores.rank_name = get_creature_name( m_scores.creature_index, 1, false, true );
	text = format_string( "%s: %s", k_rank.c_str(), m_scores.rank_name.c_str() );
	add_text( text, "rank", 1, false, false );

	// player name
	text = format_string( "%s:", k_name.c_str() );
	add_text( text, "name", 1, false, false );

	if( m_map.is_cheater() )
	{
		text = format_string( "%s", k_cheater.c_str() );
		add_text( text, "player", 1, false, false );
	} else
	{
		// create edit box
		t_text_edit_handler handler;

		rect = m_layout->find( "player" )->get_rect();
		// determine row, column where edit box will be placed
		point.x = 0;
		point.y = 0;
		if( text.size() > 0 )
			point.x = m_layout->find( "name" )->get_rect().left + get_font( rect.height() )->get_width( text.c_str() );
		rect.left = point.x;
		m_edit_box = new t_text_edit_window( get_font( rect.height() ), rect, this,
											 m_scores.human_player->get_name(), t_pixel_24(0,0,0) );
		m_edit_box->set_drop_shadow( true, t_pixel_24(200,200,200));
		handler = bound_handler( *this, &t_score_dialog::name_change );
		m_edit_box->set_change_handler( handler );
		handler = bound_handler( *this, &t_score_dialog::name_finished );
		m_edit_box->set_end_edit_handler( handler );
	}
}

// ---------------------------------------------------------------------
// score dialog
// ---------------------------------------------------------------------
static t_external_string const k_score_title( "title.score" );
void t_score_dialog::initialize()
{
	// calculate the final scores
	calculate_scores( m_map, m_winner_team, m_scores );

	m_layout = g_layout.get();
	m_difficulty_icons = g_difficulty_icons.get();

	//////////////////////////////////////////////////////////////////
 	// find dimensions & center
	t_screen_point        origin(0,0);
	t_bitmap_layer const* layer = m_layout->find( "background" );
	t_screen_rect		  rect = layer->get_rect();

	set_bitmap( layer );
	rect += t_screen_point( (get_parent()->get_width() - rect.width()) / 2, 
		                           (get_parent()->get_height() - rect.height()) / 2 );
	move( rect );
	set_drop_shadow();

	//////////////////////////////////////////////////////////////////

	// add title
	t_text_window* window;
	layer = m_layout->find( "title" );
	rect = layer->get_rect();
	window = new t_text_window( get_font( rect.height() ), rect, this, 
		                         k_score_title, t_pixel_24(0,0,0) );
	window->set_center_horizontal();
	window->set_center_vertical();
	window->set_drop_shadow( true, t_pixel_24(200,200,200));

	create_text();
	create_icons();
	create_buttons();
}

// ------------------------------------------------------------------
// save game dialog
// respond to a change in the edit box
// ------------------------------------------------------------------
void t_score_dialog::name_change( t_text_edit_window* )
{
}

// ------------------------------------------------------------------
// save game dialog
// respond to a change in the edit box
// ------------------------------------------------------------------
void t_score_dialog::name_finished( t_text_edit_window* )
{
}
